﻿#ifndef QTTAUDIO_QTTAUDIO_H
#define QTTAUDIO_QTTAUDIO_H

#if defined(_WIN32) || defined(__CYGWIN__)
#define QTT_PUBLIC_CALLBACK __stdcall
#define QTT_PUBLIC __declspec(dllexport)
#else
#define QTT_PUBLIC __attribute__((visibility("default")))
#if !defined(ANDROID) && !defined(APPLE)
#define LINUX_DEVICE
#include "QttSoundCard.h"
#endif
#endif

/**
 * 声音基础API
 */

namespace Qtt {
    /**
     * AudioEngine运行模式,切换模式需要先stop后,重新start
     */
    enum WorkMode {
        JUST_PLAYBACK,  //只听不说,适合听众使用
        RECORD_PLAYBACK  //又听又说,适合主播或者上麦用户
    };
	/**
	* 编解码类型
	*/
	enum CodecType {
		SIGNED_16BIT_LITTLE_PCM,  //文件混音使用,支持PCM输入混音
		QTT_TRANSPORT_AUDIO  //通话网络编码传输格式
	};

    class AudioParams {
    public:
        int aec_level; //AEC等级,-1到2,默认是2,-1是关闭
        int agc_level; //-1到0,-1是关闭
        int ans_level; //-1到0,-1是关闭
        int aec_delay; //声学回声时延,默认是0
        int samplerate; //采样率
        int channel;   //声道数,目前只支持1
        int bitrate;   //比特率
        float ng_thres; //降噪阈值,默认0.02，越大降噪越厉害,但可能会损害正常通话
        AudioParams() {
            aec_level = 2;
            agc_level = 0;
            ans_level = 0;
            aec_delay = 0;
            samplerate = 16000;
            channel = 1;
            bitrate = 64000;
            ng_thres = 0.02f;
        }
    };

    /**
     * 声音数据观察者
    */
    class DataObserver {
    public:
        virtual ~DataObserver() {};

        /**
         * 是否打开observerId的数据回调,影响onData
         * @param observerId
         * @return false时,该observerId不会回调onData函数
         */
        virtual bool dataEnabled(int observerId) = 0;
        /**
         * 获取到数据
         * @param buf
         * @param len
         * @param observerId
         */
        virtual void onData(char *buf, const int len, int observerId) = 0;
    };

    /**
     * 声音事件观察者
     */
    class EventObserver {
    public:
	    virtual ~EventObserver() {};
		/**
		 * 控制是否事件回调
		 * @param observerId
		 * @return true要事件回调；false不要事件回调
		 */
	    virtual bool eventEnabled(int observerId) = 0;
	    /**
	     * 事件回调函数，说话状态改变就会触发回调
	     * @param event_id 0未说话，1在说话；-1针对mic被占用情况
	     * @param observerId
	     */
	    virtual void onEvent(const int event_id, int observerId) = 0;
    };

    /**
     * 以AudioEngine作为参考系,AudioSource为输入声源抽象,可以是远端输入声源,可以是混音文件声源
     */
    class AudioSource {
    public:
        virtual ~AudioSource() {};

        /**
         * 设置说话检测
         * @param observer
         */
        virtual void setEventObsever(EventObserver *observer, int observerId) = 0;
        /**
         * 设置解码参数
         * @param samplerate 采样率
         * @param channels 声道数,1或2
         */
        virtual void setDecodeParam(int samplerate, int channels) = 0;

	    virtual void setDecodeType(CodecType codecType) = 0;
	    /**
         * 启动工作
         * @return 0成功,其他失败
         */
        virtual int start() = 0;
        /**
         * 返回是否正在工作
         * @return
         */
        virtual bool isStarted() = 0;
        /**
         * 写入数据
         * @param buf
         * @param len
         * @return 0成功,其他失败
         */
        virtual int write(char *buf, int len) = 0;
        /**
         * 调节写入的音量
         * @param vol
         */
        virtual void adjustVolume(float vol) = 0;
        /**
         * 停止工作
         * @return 0成功,其他失败
         */
        virtual int stop() = 0;
    };

    /**
     * AudioStream是对语音单向流的抽象,可以有多个AudioSource作为混音输入,但只有一个AudioSink输出
     */
    class AudioStream {
    public:
        virtual ~AudioStream() {};
        /**
         * 创建类网络传输播放的AudioSource
         * @return AudioSource指针
         */
        virtual AudioSource *createRemoteSource() = 0;
        /**
         * 创建类文件播放的AudioSource
         * @return AudioSource指针
         */
        virtual AudioSource *createFileSource() = 0;
        /**
         * 设置数据观察者,对于采集输入流,可以获取mic的采集数据
         * @param observer
         * @param observerId
         */
        virtual void setAudioSink(DataObserver *observer, int observerId) = 0;
        /**
         * 获取数据观察者
         * @return DataObserver指针
         */
        virtual DataObserver *getAudioSink() = 0;
    };

    class AudioEngine {
    public:
        virtual ~AudioEngine() {};
        /**
         * 设置音频参数
         * @param
         */
        virtual void setAudioParams(AudioParams *params) = 0;
#ifdef LINUX_DEVICE
		/**
         * 针对嵌入式linux,用户可以继承SoundCard类实现声音的采集和播放模型
         * @param recorder 声音采集对象
         * @param player 声音播放对象
         */
		virtual void useCustomeSoundCard(SoundCard *recorder, SoundCard *player) = 0;
#endif
        /**
         * 从AudioEngine获得输出播放流,负责播放混音
         * @return AudioStream指针
         */
        virtual AudioStream *getOutputStream() = 0;
        /**
         * 从AudioEngine获得采集输入流,负责采集混音
         * @return AudioStream指针
         */
        virtual AudioStream *getInputStream() = 0;
        /**
         * 检测设备声学回声时延
         * @return 毫秒
         */
        virtual int detectEcho() = 0;
        /**
         * 设置mic的事件观察者,比如mic占用,或者检测说话状态
         * @param observer
         * @param observerId
         */
        virtual void setRecordEventObsever(EventObserver *observer, int observerId) = 0;
        /**
         * 开启工作
         * @param mode 只听不说,还是又说又听
         * @return 0为成功,其他为失败
         */
        virtual int start(WorkMode mode) = 0;
		 /**
          * mic采集的数据回调，PCM格式，采样率由setAudioParams方法决定
          * @param observer 数据监听器
          * @param observerId 数据监听器id，用以区分不同的数据来源
          * @param bufSize 设置数据监听器每次回调的数据大小,-1为系统默认值
          */
         virtual void setRecordDataObsever(DataObserver *observer, int observerId, int bufSize) = 0;
         /**
          * 待播放的数据回调，PCM格式，采样率由setAudioParams方法决定
          * @param observer 数据监听器
          * @param observerId 数据监听器id，用以区分不同的数据来源
          * @param bufSize 设置数据监听器每次回调的数据大小,-1为系统默认值
          */
         virtual void setPlaybackDataObsever(DataObserver *observer, int observerId, int bufSize) = 0;
        /**
         * 是否在运行
         * @return true在运行,false停止了
         */
        virtual bool isStarted() = 0;
        /**
         * 调节mic采集音量
         * @param val 默认是1.0(100%),建议0-3.0f调节
         */
        virtual void adjustMicVolume(float val) = 0;
        /**
         * 调节speaker播放音量
         * @param val 默认是1.0(100%),建议0-3.0f调节
         */
        virtual void adjustPlayVolume(float val) = 0;
        /**
         * 启用近场啸叫抑制，如果通话设备之间离得近，可以开启此功能；默认为关闭
         * @param enable true启用；false不启用
         */
        virtual void enableHowlingSuppression(bool enable) = 0;
        /**
         * 录制经过SDK所有的声音，存为wav文件
         * @param recFile 待保存的wav文件路径
         */
        virtual void startRecord(const char *recFile) = 0;
        /**
         * 停止录音
         */
        virtual void stopRecord() = 0;
        /**
         * 停止工作
         */
        virtual void stop() = 0;
    };

	class AudioFactory {
	public:
	    /**
	     * 设置授权信息,GetEngineInstance方法前非必须调用
	     * @param licenseDir 授权文件存放目录
	     * @param userSerial 用户序列号,便于设备标示绑定
	     */
		QTT_PUBLIC static void SetLicense(const char* licenseDir, const char* userSerial);
		/**
		 * 设置appkey,GetEngineInstance前必须设置
		 * @param appkey
		 */
		QTT_PUBLIC static void SetAppkey(const char* appkey);
		/**
		 * 初始化获取AudioEngine对象指针,单例
		 * @return AudioEngine对象指针
		 */
		QTT_PUBLIC static AudioEngine *GetEngineInstance();

		QTT_PUBLIC static const char* GetError();
	};

}

#endif //QTTAUDIO_QTTAUDIO_H